package com.qj.log;

import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author dlw
 * @date 2025-05-29 16:47
 */
@Aspect
@Slf4j
@Component
@ConditionalOnProperty(name = {"log.aspect.enable"}, havingValue = "true", matchIfMissing = true)
public class LogAspect {

    //通过方法对Controller和Service设置切点
    @Pointcut("execution(* com.qj.*.controller.*Controller.*(..)) || execution(* com.qj.*.service.*Service.*(..))")
    public void pointCut() {
    }

    /**
     * @param pjp
     * @return Object
     * @description: 方法切点方式(使用 @ Around增强方法 ， 通过ProceedingJoinPoint获取方法签名及参数)
     * @author: dlw
     * @date: 2025/5/29 16:51
     * @Around("pointCut()")
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        // 1.获取请求参数
        Object[] reqArgs = pjp.getArgs();
        String req = new Gson().toJson(reqArgs);
        // 2.获取方法
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        String methodName = methodSignature.getDeclaringType().getName() + "."
                + methodSignature.getName();
        log.info("method:{},req:{}", methodName, req);
        long startTime = System.currentTimeMillis();
        // 切面需要抛出异常，不能try-catch，不然相当于将业务方法所有异常给捕获了
        Object responseObj = pjp.proceed();
        String resp = new Gson().toJson(responseObj);
        long endTime = System.currentTimeMillis();
        log.info("method:{},resp:{}", methodName, resp);
        log.info("method:{},costTime:{}", methodName, endTime - startTime);
        // 之前无返回，导致获取完数据被日志切面截胡，导致返回为null
        return responseObj;
    }

//    /**
//     * @param joinPoint
//     * @param logTrace
//     * @return Object
//     * @description:注解方式(使用@Around增强方法，通过ProceedingJoinPoint获取方法签名及参数)
//     * @author: dlw
//     * @date: 2025/5/29 17:22
//     */
//    @Around("@annotation(logTrace)")
//    public Object logAround(ProceedingJoinPoint joinPoint, LogTrace logTrace) throws Throwable {
//        // 1.获取请求参数
//        Object[] reqArgs = joinPoint.getArgs();
//        String req = new Gson().toJson(reqArgs);
//
//        String methodName = joinPoint.getSignature().getName();
//        log.info("[{}] 开始参数: {}", methodName, req);
//        long startTime = System.currentTimeMillis();
//
//        Object result = joinPoint.proceed();
//        String resp = new Gson().toJson(result);
//        log.info("[{}] 执行结果: {}", methodName, resp);
//        log.info("[{}] 执行耗时: {}ms ", methodName, System.currentTimeMillis() - startTime);
//        return result;
//    }
//
//    /**
//     * @param logTrace
//     * @param ex
//     * @description:在切面中添加@AfterThrowing拦截异常并记录堆栈
//     * @author: dlw
//     * @date: 2025/5/29 16:50
//     */
//    @AfterThrowing(pointcut = "@annotation(logTrace)", throwing = "ex")
//    public void logException(LogTrace logTrace, Exception ex) {
//        log.error("[{}] 执行异常 - 原因: {}", logTrace.module(), ex.getMessage(), ex);
//    }
}
